package cate.game.framework.index;

import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Transient;
import reactor.core.publisher.Flux;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

@ToString
@Data
public class IndexedList<INDEXED_KEY, INDEXED_VALUE> {

    private CopyOnWriteArrayList<INDEXED_VALUE> valueList;

    @Transient
    private final Map<String, Map<INDEXED_KEY, INDEXED_VALUE>> indexMap;

    public IndexedList() {
        this.valueList = new CopyOnWriteArrayList<>();
        this.indexMap = new ConcurrentHashMap<>();
    }

    public void addValue(INDEXED_VALUE value) {
        this.valueList.add(value);
    }

    public void addIndex(String indexedName, INDEXED_KEY key, INDEXED_VALUE value) {
        Map<INDEXED_KEY, INDEXED_VALUE> map = this.indexMap.computeIfAbsent(indexedName, s -> new ConcurrentHashMap<>());
        map.put(key, value);
    }

    public boolean contains(String indexedName, INDEXED_KEY key) {
        return getIndex(indexedName).containsKey(key);
    }

    public Map<INDEXED_KEY, INDEXED_VALUE> getIndex(String indexName) {
        return indexMap.computeIfAbsent(indexName, m -> new ConcurrentHashMap<>());
    }

    public Flux<INDEXED_VALUE> asFlux() {
        return getValueList().size() > 0 ? Flux.fromIterable(getValueList()) : Flux.empty();
    }

    public void clear() {
        this.valueList.clear();
        this.indexMap.clear();
    }
}
